package team.bailan.entity.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import team.bailan.common.enums.CardTypeEnum;
import team.bailan.common.process.dealcard.DealCards;

import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Card {
    public int decor; // 花色： 1-红桃 2-方片 3-黑桃 4-梅花
    public int cardFace; // 牌面： 1-15 （14小王，15大王）
    public int value; // 优先级：3-1 4-2...

    public static CardType getCardType(List<Card> cardList) {
        CardTypeFlag cardTypeFlag = new CardTypeFlag();
        DealCards.cardsSort(cardList);
        if (cardList.size() == 1) {
            return new CardType(CardTypeEnum.CARD_A, 0, cardList.get(0).value);
        } else if (cardList.size() == 2) {
            if (cardList.get(0).value == cardList.get(1).value) {
                return new CardType(CardTypeEnum.CARD_AA, 0, cardList.get(0).value);
            } else if (cardList.get(0).value == 14 && cardList.get(1).value == 15) {
                return new CardType(CardTypeEnum.CARD_WZ, 0, 100);
            } else {
                return new CardType(CardTypeEnum.CARD_INVALID, 0, 0);
            }
        } else if (cardList.size() == 3) {
            if (cardList.get(0).value == cardList.get(1).value && cardList.get(1).value == cardList.get(2).value) {
                return new CardType(CardTypeEnum.CARD_AAA, 1, cardList.get(0).value);
            } else {
                return new CardType(CardTypeEnum.CARD_INVALID, 0, 0);
            }
        } else if (cardList.size() == 4) {
            if (cardList.get(0).value == cardList.get(1).value && cardList.get(1).value == cardList.get(2).value
                    && cardList.get(2).value == cardList.get(3).value) {
                return new CardType(CardTypeEnum.CARD_AAAA, 0, cardList.get(0).value);
            } else if (cardList.get(0).value == cardList.get(1).value && cardList.get(1).value == cardList.get(2).value
                    && cardList.get(0).value != cardList.get(3).value || cardList.get(1).value == cardList.get(2).value
                    && cardList.get(2).value == cardList.get(3).value && cardList.get(0).value != cardList.get(1).value) {
                return new CardType(CardTypeEnum.CARD_AAAB, 1, cardList.get(1).value);
            } else {
                return new CardType(CardTypeEnum.CARD_INVALID, 0, 0);
            }
        } else if (cardList.size() == 5) {
            if (cardList.get(0).value == cardList.get(1).value && cardList.get(1).value == cardList.get(2).value
                    && cardList.get(3).value == cardList.get(4).value || cardList.get(0).value == cardList.get(1).value
                    && cardList.get(2).value == cardList.get(3).value && cardList.get(3).value == cardList.get(4).value) {
                return new CardType(CardTypeEnum.CARD_AAABB, 1, cardList.get(2).value);
            } else if (judgeStraight(cardList)){
                return new CardType(CardTypeEnum.CARD_ABCDE, 5, cardList.get(0).value);
            } else {
                return new CardType(CardTypeEnum.CARD_INVALID, 0, 0);
            }
        } else if (cardList.size() == 6) {
            if (cardList.get(0).value == cardList.get(1).value && cardList.get(1).value == cardList.get(2).value
                    && cardList.get(2).value == cardList.get(3).value || cardList.get(2).value == cardList.get(3).value
                    && cardList.get(3).value == cardList.get(4).value && cardList.get(4).value == cardList.get(5).value
                    || cardList.get(1).value == cardList.get(2).value && cardList.get(2).value == cardList.get(3).value
                    && cardList.get(3).value == cardList.get(4).value) {
                return new CardType(CardTypeEnum.CARD_AAAABC, 0, cardList.get(2).value);
            } else if (judgeStraight(cardList)) {
                return new CardType(CardTypeEnum.CARD_ABCDE, 6, cardList.get(0).value);
            } else if ((cardTypeFlag = judgePlane(cardList)).flag) {
                return cardTypeFlag.cardType;
            } else if (judgeSuccessivePairs(cardList)) {
                return new CardType(CardTypeEnum.CARD_AABBCC, 3, cardList.get(0).value);
            } else {
                return new CardType(CardTypeEnum.CARD_INVALID, 0, 0);
            }
        } else if (cardList.size() > 6) {
            if (judgeStraight(cardList)) {
                return new CardType(CardTypeEnum.CARD_ABCDE, cardList.size(), cardList.get(0).value);
            } else if (judgeSuccessivePairs(cardList)) {
                return new CardType(CardTypeEnum.CARD_AABBCC, cardList.size() / 2, cardList.get(0).value);
            } else if ((cardTypeFlag = judgePlane(cardList)).flag) {
                return cardTypeFlag.cardType;
            } else if ((cardTypeFlag = judgeBombWithTwoPairs(cardList)).flag) {
                return cardTypeFlag.cardType;
            } else {
                return new CardType(CardTypeEnum.CARD_INVALID, 0, 0);
            }
        } else {
            return new CardType(CardTypeEnum.CARD_INVALID, 0, 0);
        }
    }

    public static boolean judgeStraight(List<Card> cardList) {
        if (cardList.size() < 5) {
            return false;
        }
        int value = cardList.get(0).value;
        for (Card card : cardList) {
            if (card.value > 12) {
                return false;
            }

            if (card.value != value) {
                return false;
            } else {
                value += 1;
            }
        }
        return true;
    }

    public static boolean judgeSuccessivePairs(List<Card> cardList) {
        if (cardList.size() % 2 == 1 || cardList.size() < 6) {
            return false;
        }
        int value = cardList.get(0).value;
        for (int i = 0; i < cardList.size(); i++) {
            if (cardList.get(i).value > 12) {
                return false;
            }
            if (i % 2 == 0) {
                if (cardList.get(i).value != value) {
                    return false;
                }
            } else {
                if (cardList.get(i).value != value) {
                    return false;
                } else {
                    value += 1;
                }
            }
        }
        return true;
    }

    public static CardTypeFlag judgePlane(List<Card> cardList) {
        if (cardList.size() < 6) {
            return new CardTypeFlag(false, new CardType(CardTypeEnum.CARD_INVALID, 0, 0));
        }
        int pos = -1;
        int count = 0;
        int tmp = 0;
        int cardValue = 0;
        for (int i = 0; i < cardList.size(); i++) {
            if (judgeTheSame(cardList, i, 3)) {
                cardValue = cardList.get(i).value;
                if (cardList.get(i).value > 12) {
                    return new CardTypeFlag(false, new CardType(CardTypeEnum.CARD_INVALID, 0, 0));
                }
                pos = i;
                count = 1;
                if (cardList.get(i).value == cardList.get(i + 3).value) {
                    i += 1;
                }
                while (judgeTheSame(cardList, i + 3, 3)) {
                    if (cardList.get(i + 3).value > 12 || cardList.get(i).value + 1 != cardList.get(i + 3).value) {
                        return new CardTypeFlag(false, new CardType(CardTypeEnum.CARD_INVALID, 0, 0));
                    }
                    count += 1;
                    i += 3;
                }
                break;
            }
        }
        if (pos == -1) {
            return new CardTypeFlag(false, new CardType(CardTypeEnum.CARD_INVALID, 0, 0));
        }

        if (cardList.size() - 3 * count == 0) {
            return new CardTypeFlag(true, new CardType(CardTypeEnum.CARD_AAABBB, count, cardList.get(0).value));
        } else if (cardList.size() - 3 * count == count) {
            return new CardTypeFlag(true, new CardType(CardTypeEnum.CARD_AAABBBCD, count, cardValue));
        } else if (cardList.size() - 3 * count == count * 2) {
            int value = 0;
            for (int i = 0; i < pos; i++) {
                if (i % 2 == 0) {
                    value = cardList.get(i).value;
                } else {
                    if (cardList.get(i).value != value) {
                        return new CardTypeFlag(false, new CardType(CardTypeEnum.CARD_INVALID, 0, 0));
                    }
                }
            }
            for (int i = pos + 3 * count; i < cardList.size(); i++) {
                if (tmp % 2 == 0) {
                    value = cardList.get(i).value;
                } else {
                    if (cardList.get(i).value != value) {
                        return new CardTypeFlag(false, new CardType(CardTypeEnum.CARD_INVALID, 0, 0));
                    }
                }
                tmp += 1;
            }
            return new CardTypeFlag(true, new CardType(CardTypeEnum.CARD_AAABBBCCDD, count, cardValue));
        } else {
            return new CardTypeFlag(false, new CardType(CardTypeEnum.CARD_INVALID, 0, 0));
        }

    }

    public static boolean judgeTheSame(List<Card> cardList, int pos, int count) {
        if (pos >= cardList.size()) {
            return false;
        }
        int value = cardList.get(pos).value;
        if (pos + count > cardList.size()) {
            return false;
        }
        for (int i = pos + 1; i < pos + count; i++) {
            if (cardList.get(i).value != value) {
                return false;
            }
        }
        return true;
    }

    public static CardTypeFlag judgeBombWithTwoPairs(List<Card> cardList) {
        if (cardList.size() != 8) {
            return new CardTypeFlag(false, new CardType(CardTypeEnum.CARD_INVALID, 0, 0));
        }
        for (int i = 0; i < 5; i++) {
            if (judgeTheSame(cardList, i, 4)) {
                if (i == 0) {
                    if (cardList.get(4).value == cardList.get(5).value && cardList.get(6).value == cardList.get(7).value) {
                        return new CardTypeFlag(true, new CardType(CardTypeEnum.CARD_AAAABBCC, 1, cardList.get(0).value));
                    }
                } else if (i == 2) {
                    if (cardList.get(0).value == cardList.get(1).value && cardList.get(6).value == cardList.get(7).value) {
                        return new CardTypeFlag(true, new CardType(CardTypeEnum.CARD_AAAABBCC, 1, cardList.get(2).value));
                    }
                } else if (i == 4) {
                    if (cardList.get(0).value == cardList.get(1).value && cardList.get(2).value == cardList.get(3).value) {
                        return new CardTypeFlag(true, new CardType(CardTypeEnum.CARD_AAAABBCC, 1, cardList.get(4).value));
                    }
                } else {
                    return new CardTypeFlag(false, new CardType(CardTypeEnum.CARD_INVALID, 0, 0));
                }
            }
        }
        return new CardTypeFlag(false, new CardType(CardTypeEnum.CARD_INVALID, 0, 0));
    }


}

